/*
 * Lapack.cs
 *
 * LAPACK provider for AMD's ACML.
 *
 * Copyright (c) 2005, dnAnalytics. All rights reserved.
 */
using System;

namespace dnAnalytics.Nli.Acml {
	/// <summary>
	/// Summary description for Mkl Lapack.
	/// </summary>
	internal sealed class LapackCvf : ILapack {
		private static readonly ILapack instance = new LapackCvf();

		private LapackCvf() {}

		#region Public Members

		public static ILapack Instance {
			get { return instance; }
		}

		public int Sgeqp3(int m, int n, float[] a, int lda, int[] jpvt, float[] tau) {
			float[] work = new float[Math.Max(1, 3*n + 1)];
			return Sgeqp3(m, n, a, lda, jpvt, tau, work);
		}

		public int Sgeqp3(int m, int n, float[] a, int lda, int[] jpvt, float[] tau, float[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.SGEQP3(ref m, ref n, a, ref lda, jpvt, tau, work, ref len, ref info);
			return info;
		}

		public int Sgesvd(char jobu, char jobvt, int m, int n, float[] a, int lda, float[] s, float[] u, int ldu, float[] vt, int ldvt) {
			float[] work = new float[Math.Max((3*Math.Min(m, n) + Math.Max(m, n)), 5*Math.Min(m, n))];
			return Sgesvd(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work);
		}

		public int Sgesvd(char jobu, char jobvt, int m, int n, float[] a, int lda, float[] s, float[] u, int ldu, float[] vt, int ldvt, float[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.SGESVD(ref jobu, 1, ref jobvt, 1, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref len, ref info);
			return info;
		}

		public int Sgetrf(int m, int n, float[] a, int lda, out int[] ipiv) {
			int info = 0;
			ipiv = new int[m];
			SafeNativeMethods.SGETRF(ref m, ref n, a, ref lda, ipiv, ref info);
			return info;
		}

		public int Sgetri(int n, float[] a, int lda, int[] ipiv) {
			int bs = Ilaenv(1, "SGETRI", "", n, -1, -1, -1);
			float[] work = new float[n*bs];
			return Sgetri(n, a, lda, ipiv, work);
		}

		public int Sgetri(int n, float[] a, int lda, int[] ipiv, float[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.SGETRI(ref n, a, ref lda, ipiv, work, ref len, ref info);
			return info;
		}

		public int Sgetrs(char trans, int n, int nrhs, float[] a, int lda, int[] ipiv, float[] b, int ldb) {
			int info = 0;
			SafeNativeMethods.SGETRS(ref trans, 1, ref n, ref nrhs, a, ref lda, ipiv, b, ref ldb, ref info);
			return info;
		}

		public int Sorgqr(int m, int n, int k, float[] a, int lda, float[] tau) {
			int bs = Ilaenv(1, "SORGQR", "", m, n, k, -1);
			float[] work = new float[n*bs];
			return Sorgqr(m, n, k, a, lda, tau, work);
		}

		public int Sorgqr(int m, int n, int k, float[] a, int lda, float[] tau, float[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.SORGQR(ref m, ref n, ref k, a, ref lda, tau, work, ref len, ref info);
			return info;
		}

		public int Sormqr(char side, char trans, int m, int n, int k, float[] a, int lda, float[] tau, float[] c, int ldc) {
			string opts = side.ToString() + trans.ToString();
			int bs = Ilaenv(1, "SORMQR", opts, m, n, k, -1);
			float[] work = null;
			if (side == 'L' || side == 'l') {
				work = new float[n*bs];
			} else {
				work = new float[m*bs];
			}
			return Sormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work);
		}

		public int Sormqr(char side, char trans, int m, int n, int k, float[] a, int lda, float[] tau, float[] c, int ldc, float[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.SORMQR(ref side, 1, ref trans, 1, ref m, ref n, ref k, a, ref lda, tau, c, ref ldc, work, ref len, ref info);
			return info;
		}

		public int Spotrf(char uplo, int n, float[] a, int lda) {
			int info = 0;
			SafeNativeMethods.SPOTRF(ref uplo, 1, ref n, a, ref lda, ref info);
			return info;
		}

		public int Spotri(char uplo, int n, float[] a, int lda) {
			int info = 0;
			SafeNativeMethods.SPOTRI(ref uplo, 1, ref n, a, ref lda, ref info);
			return info;
		}

		public int Spotrs(char uplo, int n, int nrhs, float[] a, int lda, float[] b, int ldb) {
			int info = 0;
			SafeNativeMethods.SPOTRS(ref uplo, 1, ref n, ref nrhs, a, ref lda, b, ref ldb, ref info);
			return info;
		}

		public int Dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau) {
			double[] work = new double[Math.Max(1, 3*n + 1)];
			return Dgeqp3(m, n, a, lda, jpvt, tau, work);
		}

		public int Dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.DGEQP3(ref m, ref n, a, ref lda, jpvt, tau, work, ref len, ref info);
			return info;
		}

		public int Dgesvd(char jobu, char jobvt, int m, int n, double[] a, int lda, double[] s, double[] u, int ldu, double[] vt, int ldvt) {
			double[] work = new double[Math.Max((3*Math.Min(m, n) + Math.Max(m, n)), 5*Math.Min(m, n))];
			return Dgesvd(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work);
		}

		public int Dgesvd(char jobu, char jobvt, int m, int n, double[] a, int lda, double[] s, double[] u, int ldu, double[] vt, int ldvt, double[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.DGESVD(ref jobu, 1, ref jobvt, 1, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref len, ref info);
			return info;
		}

		public int Dgetrf(int m, int n, double[] a, int lda, out int[] ipiv) {
			int info = 0;
			ipiv = new int[m];
			SafeNativeMethods.DGETRF(ref m, ref n, a, ref lda, ipiv, ref info);
			return info;
		}

		public int Dgetri(int n, double[] a, int lda, int[] ipiv) {
			int bs = Ilaenv(1, "DGETRI", "", n, -1, -1, -1);
			double[] work = new double[n*bs];
			return Dgetri(n, a, lda, ipiv, work);
		}

		public int Dgetri(int n, double[] a, int lda, int[] ipiv, double[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.DGETRI(ref n, a, ref lda, ipiv, work, ref len, ref info);
			return info;
		}

		public int Dgetrs(char trans, int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
			int info = 0;
			SafeNativeMethods.DGETRS(ref trans, 1, ref n, ref nrhs, a, ref lda, ipiv, b, ref ldb, ref info);
			return info;
		}

		public int Dorgqr(int m, int n, int k, double[] a, int lda, double[] tau) {
			int bs = Ilaenv(1, "DORGQR", "", m, n, k, -1);
			double[] work = new double[n*bs];
			return Dorgqr(m, n, k, a, lda, tau, work);
		}

		public int Dorgqr(int m, int n, int k, double[] a, int lda, double[] tau, double[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.DORGQR(ref m, ref n, ref k, a, ref lda, tau, work, ref len, ref info);
			return info;
		}

		public int Dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc) {
			string opts = side.ToString() + trans.ToString();
			int bs = Ilaenv(1, "DORMQR", opts, m, n, k, -1);
			double[] work = null;
			if (side == 'L' || side == 'l') {
				work = new double[n*bs];
			} else {
				work = new double[m*bs];
			}
			return Dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work);
		}

		public int Dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.DORMQR(ref side, 1, ref trans, 1, ref m, ref n, ref k, a, ref lda, tau, c, ref ldc, work, ref len, ref info);
			return info;
		}

		public int Dpotrf(char uplo, int n, double[] a, int lda) {
			int info = 0;
			SafeNativeMethods.DPOTRF(ref uplo, 1, ref n, a, ref lda, ref info);
			return info;
		}

		public int Dpotri(char uplo, int n, double[] a, int lda) {
			int info = 0;
			SafeNativeMethods.DPOTRI(ref uplo, 1, ref n, a, ref lda, ref info);
			return info;
		}

		public int Dpotrs(char uplo, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
			int info = 0;
			SafeNativeMethods.DPOTRS(ref uplo, 1, ref n, ref nrhs, a, ref lda, b, ref ldb, ref info);
			return info;
		}

		public int Cgeqp3(int m, int n, ComplexFloat[] a, int lda, int[] jpvt, ComplexFloat[] tau) {
			ComplexFloat[] work = new ComplexFloat[Math.Max(1, n + 1)];
			float[] rwork = new float[Math.Max(1, 2*n)];
			return Cgeqp3(m, n, a, lda, jpvt, tau, work, rwork);
		}

		public int Cgeqp3(int m, int n, ComplexFloat[] a, int lda, int[] jpvt, ComplexFloat[] tau, ComplexFloat[] work, float[] rwork) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.CGEQP3(ref m, ref n, a, ref lda, jpvt, tau, work, ref len, rwork, ref info);
			return info;
		}

		public int Cgetrf(int m, int n, ComplexFloat[] a, int lda, out int[] ipiv) {
			int info = 0;
			ipiv = new int[m];
			SafeNativeMethods.CGETRF(ref m, ref n, a, ref lda, ipiv, ref info);
			return info;
		}

		public int Cgetri(int n, ComplexFloat[] a, int lda, int[] ipiv) {
			int bs = Ilaenv(1, "CGETRI", "", n, -1, -1, -1);
			ComplexFloat[] work = new ComplexFloat[n*bs];
			return Cgetri(n, a, lda, ipiv, work);
		}

		public int Cgetri(int n, ComplexFloat[] a, int lda, int[] ipiv, ComplexFloat[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.CGETRI(ref n, a, ref lda, ipiv, work, ref len, ref info);
			return info;
		}

		public int Cgetrs(char trans, int n, int nrhs, ComplexFloat[] a, int lda, int[] ipiv, ComplexFloat[] b, int ldb) {
			int info = 0;
			SafeNativeMethods.CGETRS(ref trans, 1, ref n, ref nrhs, a, ref lda, ipiv, b, ref ldb, ref info);
			return info;
		}

		public int Cpotrf(char uplo, int n, ComplexFloat[] a, int lda) {
			int info = 0;
			SafeNativeMethods.CPOTRF(ref uplo, 1, ref n, a, ref lda, ref info);
			return info;
		}

		public int Cpotri(char uplo, int n, ComplexFloat[] a, int lda) {
			int info = 0;
			SafeNativeMethods.CPOTRI(ref uplo, 1, ref n, a, ref lda, ref info);
			return info;
		}

		public int Cpotrs(char uplo, int n, int nrhs, ComplexFloat[] a, int lda, ComplexFloat[] b, int ldb) {
			int info = 0;
			SafeNativeMethods.CPOTRS(ref uplo, 1, ref n, ref nrhs, a, ref lda, b, ref ldb, ref info);
			return info;
		}

		public int Cungqr(int m, int n, int k, ComplexFloat[] a, int lda, ComplexFloat[] tau) {
			int bs = Ilaenv(1, "CUNGQR", "", m, n, k, -1);
			ComplexFloat[] work = new ComplexFloat[n*bs];
			return Cungqr(m, n, k, a, lda, tau, work);
		}

		public int Cungqr(int m, int n, int k, ComplexFloat[] a, int lda, ComplexFloat[] tau, ComplexFloat[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.CUNGQR(ref m, ref n, ref k, a, ref lda, tau, work, ref len, ref info);
			return info;
		}

		public int Cunmqr(char side, char trans, int m, int n, int k, ComplexFloat[] a, int lda, ComplexFloat[] tau, ComplexFloat[] c, int ldc) {
			string opts = side.ToString() + trans.ToString();
			int bs = Ilaenv(1, "CUNMQR", opts, m, n, k, -1);
			ComplexFloat[] work = null;
			if (side == 'L' || side == 'l') {
				work = new ComplexFloat[n*bs];
			} else {
				work = new ComplexFloat[m*bs];
			}
			return Cunmqr(side, trans, m, n, k, a, lda, tau, c, ldc, work);
		}

		public int Cunmqr(char side, char trans, int m, int n, int k, ComplexFloat[] a, int lda, ComplexFloat[] tau, ComplexFloat[] c, int ldc, ComplexFloat[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.CUNMQR(ref side, 1, ref trans, 1, ref m, ref n, ref k, a, ref lda, tau, c, ref ldc, work, ref len, ref info);
			return info;
		}

		public int Zgeqp3(int m, int n, ComplexDouble[] a, int lda, int[] jpvt, ComplexDouble[] tau) {
			ComplexDouble[] work = new ComplexDouble[Math.Max(1, n + 1)];
			double[] rwork = new double[Math.Max(1, 2*n)];
			return Zgeqp3(m, n, a, lda, jpvt, tau, work, rwork);
		}

		public int Zgeqp3(int m, int n, ComplexDouble[] a, int lda, int[] jpvt, ComplexDouble[] tau, ComplexDouble[] work, double[] rwork) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.ZGEQP3(ref m, ref n, a, ref lda, jpvt, tau, work, ref len, rwork, ref info);
			return info;
		}

		public int Zgetrf(int m, int n, ComplexDouble[] a, int lda, out int[] ipiv) {
			int info = 0;
			ipiv = new int[m];
			SafeNativeMethods.ZGETRF(ref m, ref n, a, ref lda, ipiv, ref info);
			return info;
		}

		public int Zgetri(int n, ComplexDouble[] a, int lda, int[] ipiv) {
			int bs = Ilaenv(1, "ZGETRI", "", n, -1, -1, -1);
			ComplexDouble[] work = new ComplexDouble[n*bs];
			return Zgetri(n, a, lda, ipiv, work);
		}

		public int Zgetri(int n, ComplexDouble[] a, int lda, int[] ipiv, ComplexDouble[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.ZGETRI(ref n, a, ref lda, ipiv, work, ref len, ref info);
			return info;
		}

		public int Zgetrs(char trans, int n, int nrhs, ComplexDouble[] a, int lda, int[] ipiv, ComplexDouble[] b, int ldb) {
			int info = 0;
			SafeNativeMethods.ZGETRS(ref trans, 1, ref n, ref nrhs, a, ref lda, ipiv, b, ref ldb, ref info);
			return info;
		}

		public int Zpotrf(char uplo, int n, ComplexDouble[] a, int lda) {
			int info = 0;
			SafeNativeMethods.ZPOTRF(ref uplo, 1, ref n, a, ref lda, ref info);
			return info;
		}

		public int Zpotri(char uplo, int n, ComplexDouble[] a, int lda) {
			int info = 0;
			SafeNativeMethods.ZPOTRI(ref uplo, 1, ref n, a, ref lda, ref info);
			return info;
		}

		public int Zpotrs(char uplo, int n, int nrhs, ComplexDouble[] a, int lda, ComplexDouble[] b, int ldb) {
			int info = 0;
			SafeNativeMethods.ZPOTRS(ref uplo, 1, ref n, ref nrhs, a, ref lda, b, ref ldb, ref info);
			return info;
		}

		public int Zungqr(int m, int n, int k, ComplexDouble[] a, int lda, ComplexDouble[] tau) {
			int bs = Ilaenv(1, "ZUNGQR", "", m, n, k, -1);
			ComplexDouble[] work = new ComplexDouble[n*bs];
			return Zungqr(m, n, k, a, lda, tau, work);
		}

		public int Zungqr(int m, int n, int k, ComplexDouble[] a, int lda, ComplexDouble[] tau, ComplexDouble[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.ZUNGQR(ref m, ref n, ref k, a, ref lda, tau, work, ref len, ref info);
			return info;
		}

		public int Zunmqr(char side, char trans, int m, int n, int k, ComplexDouble[] a, int lda, ComplexDouble[] tau, ComplexDouble[] c, int ldc) {
			string opts = side.ToString() + trans.ToString();
			int bs = Ilaenv(1, "ZUNMQR", opts, m, n, k, -1);
			ComplexDouble[] work = null;
			if (side == 'L' || side == 'l') {
				work = new ComplexDouble[n*bs];
			} else {
				work = new ComplexDouble[m*bs];
			}
			return Zunmqr(side, trans, m, n, k, a, lda, tau, c, ldc, work);
		}

		public int Zunmqr(char side, char trans, int m, int n, int k, ComplexDouble[] a, int lda, ComplexDouble[] tau, ComplexDouble[] c, int ldc, ComplexDouble[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.ZUNMQR(ref side, 1, ref trans, 1, ref m, ref n, ref k, a, ref lda, tau, c, ref ldc, work, ref len, ref info);
			return info;
		}

		public int Cgesvd(char jobu, char jobvt, int m, int n, ComplexFloat[] a, int lda, float[] s, ComplexFloat[] u, int ldu, ComplexFloat[] vt, int ldvt) {
			ComplexFloat[] work = new ComplexFloat[2*Math.Min(m, n) + Math.Max(m, n)];
			float[] rwork = new float[Math.Max(1, 5*Math.Min(m, n))];
			return Cgesvd(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work, rwork);
		}

		public int Zgesvd(char jobu, char jobvt, int m, int n, ComplexDouble[] a, int lda, double[] s, ComplexDouble[] u, int ldu, ComplexDouble[] vt, int ldvt) {
			ComplexDouble[] work = new ComplexDouble[2*Math.Min(m, n) + Math.Max(m, n)];
			double[] rwork = new double[Math.Max(1, 5*Math.Min(m, n))];
			return Zgesvd(jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, work, rwork);
		}

		public int Cgesvd(char jobu, char jobvt, int m, int n, ComplexFloat[] a, int lda, float[] s, ComplexFloat[] u, int ldu, ComplexFloat[] vt, int ldvt, ComplexFloat[] work, float[] rwork) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.CGESVD(ref jobu, 1, ref jobvt, 1, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref len, rwork, ref info);
			return info;
		}

		public int Zgesvd(char jobu, char jobvt, int m, int n, ComplexDouble[] a, int lda, double[] s, ComplexDouble[] u, int ldu, ComplexDouble[] vt, int ldvt, ComplexDouble[] work, double[] rwork) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.ZGESVD(ref jobu, 1, ref jobvt, 1, ref m, ref n, a, ref lda, s, u, ref ldu, vt, ref ldvt, work, ref len, rwork, ref info);
			return info;
		}

		public int Sgels(char trans, int m, int n, int nrhs, float[] a, int lda, float[] b, int ldb) {
			int bs = Ilaenv(1, "SGELS", trans.ToString(), m, n, nrhs, -1);
			float[] work = new float[Math.Min(m, n) + Math.Max(m, Math.Max(n, nrhs))*bs];
			return Sgels(trans, m, n, nrhs, a, lda, b, ldb, work);
		}

		public int Sgels(char trans, int m, int n, int nrhs, float[] a, int lda, float[] b, int ldb, float[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.SGELS(ref trans, 1, ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, work, ref len, ref info);
			return info;
		}

		public int Cgels(char trans, int m, int n, int nrhs, ComplexFloat[] a, int lda, ComplexFloat[] b, int ldb) {
			int bs = Ilaenv(1, "CGELS", trans.ToString(), m, n, nrhs, -1);
			ComplexFloat[] work = new ComplexFloat[Math.Min(m, n) + Math.Max(m, Math.Max(n, nrhs))*bs];
			return Cgels(trans, m, n, nrhs, a, lda, b, ldb, work);
		}

		public int Cgels(char trans, int m, int n, int nrhs, ComplexFloat[] a, int lda, ComplexFloat[] b, int ldb, ComplexFloat[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.CGELS(ref trans, 1, ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, work, ref len, ref info);
			return info;
		}

		public int Dgels(char trans, int m, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
			int bs = Ilaenv(1, "DGELS", trans.ToString(), m, n, nrhs, -1);
			double[] work = new double[Math.Min(m, n) + Math.Max(m, Math.Max(n, nrhs))*bs];
			return Dgels(trans, m, n, nrhs, a, lda, b, ldb, work);
		}

		public int Dgels(char trans, int m, int n, int nrhs, double[] a, int lda, double[] b, int ldb, double[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.DGELS(ref trans, 1, ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, work, ref len, ref info);
			return info;
		}

		public int Zgels(char trans, int m, int n, int nrhs, ComplexDouble[] a, int lda, ComplexDouble[] b, int ldb) {
			int bs = Ilaenv(1, "ZGELS", trans.ToString(), m, n, nrhs, -1);
			ComplexDouble[] work = new ComplexDouble[Math.Min(m, n) + Math.Max(m, Math.Max(n, nrhs))*bs];
			return Zgels(trans, m, n, nrhs, a, lda, b, ldb, work);
		}

		public int Zgels(char trans, int m, int n, int nrhs, ComplexDouble[] a, int lda, ComplexDouble[] b, int ldb, ComplexDouble[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.ZGELS(ref trans, 1, ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, work, ref len, ref info);
			return info;
		}

		public int Sgelss(int m, int n, int nrhs, float[] a, int lda, float[] b, int ldb, out float[] s, ref int rank) {
			float[] work = new float[3*Math.Min(m, n) + Math.Max(2*Math.Min(m, n), Math.Max(Math.Max(m, n), nrhs))];
			float rcond = -1;
			return Sgelss(m, n, nrhs, a, lda, b, ldb, out s, rcond, ref rank, work);
		}

		public int Sgelss(int m, int n, int nrhs, float[] a, int lda, float[] b, int ldb, out float[] s, float rcond, ref int rank, float[] work) {
			int info = 0;
			int len = work.Length;
			s = new float[Math.Min(m, n)];
			SafeNativeMethods.SGELSS(ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, s, ref rcond, ref rank, work, ref len, ref info);
			return info;
		}

		public int Dgelss(int m, int n, int nrhs, double[] a, int lda, double[] b, int ldb, out double[] s, ref int rank) {
			double[] work = new double[3*Math.Min(m, n) + Math.Max(2*Math.Min(m, n), Math.Max(Math.Max(m, n), nrhs))];
			double rcond = -1;
			return Dgelss(m, n, nrhs, a, lda, b, ldb, out s, rcond, ref rank, work);
		}

		public int Dgelss(int m, int n, int nrhs, double[] a, int lda, double[] b, int ldb, out double[] s, double rcond, ref int rank, double[] work) {
			int info = 0;
			int len = work.Length;
			s = new double[Math.Min(m, n)];
			SafeNativeMethods.DGELSS(ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, s, ref rcond, ref rank, work, ref len, ref info);
			return info;
		}

		public int Cgelss(int m, int n, int nrhs, ComplexFloat[] a, int lda, ComplexFloat[] b, int ldb, out float[] s, ref int rank) {
			ComplexFloat[] work = new ComplexFloat[3*Math.Min(m, n) + Math.Max(2*Math.Min(m, n), Math.Max(Math.Max(m, n), nrhs))];
			float[] rwork = new float[Math.Max(1, 5*Math.Min(m, n))];
			float rcond = -1;
			return Cgelss(m, n, nrhs, a, lda, b, ldb, out s, rcond, ref rank, work, rwork);
		}

		public int Cgelss(int m, int n, int nrhs, ComplexFloat[] a, int lda, ComplexFloat[] b, int ldb, out float[] s, float rcond, ref int rank, ComplexFloat[] work, float[] rwork) {
			int info = 0;
			int len = work.Length;
			s = new float[Math.Min(m, n)];
			SafeNativeMethods.CGELSS(ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, s, ref rcond, ref rank, work, ref len, rwork, ref info);
			return info;
		}

		public int Zgelss(int m, int n, int nrhs, ComplexDouble[] a, int lda, ComplexDouble[] b, int ldb, out double[] s, ref int rank) {
			ComplexDouble[] work = new ComplexDouble[3*Math.Min(m, n) + Math.Max(2*Math.Min(m, n), Math.Max(Math.Max(m, n), nrhs))];
			double[] rwork = new double[Math.Max(1, 5*Math.Min(m, n))];
			double rcond = -1;
			return Zgelss(m, n, nrhs, a, lda, b, ldb, out s, rcond, ref rank, work, rwork);
		}

		public int Zgelss(int m, int n, int nrhs, ComplexDouble[] a, int lda, ComplexDouble[] b, int ldb, out double[] s, double rcond, ref int rank, ComplexDouble[] work, double[] rwork) {
			int info = 0;
			int len = work.Length;
			s = new double[Math.Min(m, n)];
			SafeNativeMethods.ZGELSS(ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, s, ref rcond, ref rank, work, ref len, rwork, ref info);
			return info;
		}

		public int Sgelsy(int m, int n, int nrhs, float[] a, int lda, float[] b, int ldb, int[] jpvt, float rcond, ref int rank) {
			int nb = Ilaenv(1, "SGELSY", "", m, n, nrhs, -1);
			int mn = Math.Min(m, n);
			int len = Math.Max((mn + 2)*n + nb*(n + 1), 2*mn + nb*nrhs);
			float[] work = new float[len];
			return Sgelsy(m, n, nrhs, a, lda, b, ldb, jpvt, rcond, ref rank, work);
		}

		public int Sgelsy(int m, int n, int nrhs, float[] a, int lda, float[] b, int ldb, int[] jpvt, float rcond, ref int rank, float[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.SGELSY(ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, jpvt, ref rcond, ref rank, work, ref len, ref info);
			return info;
		}

		public int Dgelsy(int m, int n, int nrhs, double[] a, int lda, double[] b, int ldb, int[] jpvt, double rcond, ref int rank) {
			int nb = Ilaenv(1, "DGELSY", "", m, n, nrhs, -1);
			int mn = Math.Min(m, n);
			int len = Math.Max((mn + 2)*n + nb*(n + 1), 2*mn + nb*nrhs);
			double[] work = new double[len];
			return Dgelsy(m, n, nrhs, a, lda, b, ldb, jpvt, rcond, ref rank, work);
		}

		public int Dgelsy(int m, int n, int nrhs, double[] a, int lda, double[] b, int ldb, int[] jpvt, double rcond, ref int rank, double[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.DGELSY(ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, jpvt, ref rcond, ref rank, work, ref len, ref info);
			return info;
		}

		public int Cgelsy(int m, int n, int nrhs, ComplexFloat[] a, int lda, ComplexFloat[] b, int ldb, int[] jpvt, float rcond, ref int rank) {
			int nb = Ilaenv(1, "CGELSY", "", m, n, nrhs, -1);
			int mn = Math.Min(m, n);
			int len = mn + Math.Max(Math.Max(Math.Max(2*mn, nb*(n + 1)), mn + mn*nb), mn + nb*nrhs);
			ComplexFloat[] work = new ComplexFloat[len];
			float[] rwork = new float[Math.Max(1, 2*n)];
			return Cgelsy(m, n, nrhs, a, lda, b, ldb, jpvt, rcond, ref rank, work, rwork);
		}

		public int Cgelsy(int m, int n, int nrhs, ComplexFloat[] a, int lda, ComplexFloat[] b, int ldb, int[] jpvt, float rcond, ref int rank, ComplexFloat[] work, float[] rwork) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.CGELSY(ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, jpvt, ref rcond, ref rank, work, ref len, rwork, ref info);
			return info;
		}

		public int Zgelsy(int m, int n, int nrhs, ComplexDouble[] a, int lda, ComplexDouble[] b, int ldb, int[] jpvt, double rcond, ref int rank) {
			int nb = Ilaenv(1, "ZGELSY", "", m, n, nrhs, -1);
			int mn = Math.Min(m, n);
			int len = mn + Math.Max(Math.Max(Math.Max(2*mn, nb*(n + 1)), mn + mn*nb), mn + nb*nrhs);
			ComplexDouble[] work = new ComplexDouble[len];
			double[] rwork = new double[Math.Max(1, 2*n)];
			return Zgelsy(m, n, nrhs, a, lda, b, ldb, jpvt, rcond, ref rank, work, rwork);
		}

		public int Zgelsy(int m, int n, int nrhs, ComplexDouble[] a, int lda, ComplexDouble[] b, int ldb, int[] jpvt, double rcond, ref int rank, ComplexDouble[] work, double[] rwork) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.ZGELSY(ref m, ref n, ref nrhs, a, ref lda, b, ref ldb, jpvt, ref rcond, ref rank, work, ref len, rwork, ref info);
			return info;
		}

		public float Slange(char norm, int m, int n, float[] a, int lda) {
			float[] work = new float[m];
			return Slange(norm, m, n, a, lda, work);
		}

		public float Slange(char norm, int m, int n, float[] a, int lda, float[] work) {
			return SafeNativeMethods.SLANGE(ref norm, 1, ref m, ref n, a, ref lda, work);
		}

		public double Dlange(char norm, int m, int n, double[] a, int lda) {
			double[] work = new double[m];
			return Dlange(norm, m, n, a, lda, work);
		}

		public double Dlange(char norm, int m, int n, double[] a, int lda, double[] work) {
			return SafeNativeMethods.DLANGE(ref norm, 1, ref m, ref n, a, ref lda, work);
		}

		public float Clange(char norm, int m, int n, ComplexFloat[] a, int lda) {
			float[] work = new float[m];
			return Clange(norm, m, n, a, lda, work);
		}

		public float Clange(char norm, int m, int n, ComplexFloat[] a, int lda, float[] work) {
			return SafeNativeMethods.CLANGE(ref norm, 1, ref m, ref n, a, ref lda, work);
		}

		public double Zlange(char norm, int m, int n, ComplexDouble[] a, int lda) {
			double[] work = new double[m];
			return Zlange(norm, m, n, a, lda, work);
		}

		public double Zlange(char norm, int m, int n, ComplexDouble[] a, int lda, double[] work) {
			return SafeNativeMethods.ZLANGE(ref norm, 1, ref m, ref n, a, ref lda, work);
		}

		public int Sgecon(char norm, int n, float[] a, int lda, float anorm, ref float rcond) {
			float[] work = new float[Math.Max(1, 4*n)];
			int[] iwork = new int[Math.Max(1, n)];
			return Sgecon(norm, n, a, lda, anorm, ref rcond, work, iwork);
		}

		public int Sgecon(char norm, int n, float[] a, int lda, float anorm, ref float rcond, float[] work, int[] iwork) {
			int info = 0;
			SafeNativeMethods.SGECON(ref norm, 1, ref n, a, ref lda, ref anorm, ref rcond, work, iwork, ref info);
			return info;
		}

		public int Dgecon(char norm, int n, double[] a, int lda, double anorm, ref double rcond) {
			double[] work = new double[Math.Max(1, 4*n)];
			int[] iwork = new int[Math.Max(1, n)];
			return Dgecon(norm, n, a, lda, anorm, ref rcond, work, iwork);
		}

		public int Dgecon(char norm, int n, double[] a, int lda, double anorm, ref double rcond, double[] work, int[] iwork) {
			int info = 0;
			SafeNativeMethods.DGECON(ref norm, 1, ref n, a, ref lda, ref anorm, ref rcond, work, iwork, ref info);
			return info;
		}

		public int Cgecon(char norm, int n, ComplexFloat[] a, int lda, float anorm, ref float rcond) {
			ComplexFloat[] work = new ComplexFloat[Math.Max(1, 4*n)];
			float[] rwork = new float[Math.Max(1, 2*n)];
			return Cgecon(norm, n, a, lda, anorm, ref rcond, work, rwork);
		}

		public int Cgecon(char norm, int n, ComplexFloat[] a, int lda, float anorm, ref float rcond, ComplexFloat[] work, float[] rwork) {
			int info = 0;
			SafeNativeMethods.CGECON(ref norm, 1, ref n, a, ref lda, ref anorm, ref rcond, work, rwork, ref info);
			return info;
		}

		public int Zgecon(char norm, int n, ComplexDouble[] a, int lda, double anorm, ref double rcond) {
			ComplexDouble[] work = new ComplexDouble[Math.Max(1, 4*n)];
			double[] rwork = new double[Math.Max(1, 2*n)];
			return Zgecon(norm, n, a, lda, anorm, ref rcond, work, rwork);
		}

		public int Zgecon(char norm, int n, ComplexDouble[] a, int lda, double anorm, ref double rcond, ComplexDouble[] work, double[] rwork) {
			int info = 0;
			SafeNativeMethods.ZGECON(ref norm, 1, ref n, a, ref lda, ref anorm, ref rcond, work, rwork, ref info);
			return info;
		}

		public int Sggev(char jobvl, char jobvr, int n, float[] a, int lda, float[] b, int ldb, float[] alphar, float[] alphai, float[] beta, float[] vl, int ldvl, float[] vr, int ldvr) {
			float[] work = new float[Math.Max(1, 8*n+16)];		
			return Sggev(jobvl, jobvr, n, a, lda, b, ldb, alphar, alphai, beta, vl, ldvl, vr, ldvr, work );
		}

		public int Sggev(char jobvl, char jobvr, int n, float[] a, int lda, float[] b, int ldb, float[] alphar, float[] alphai, float[] beta, float[] vl, int ldvl, float[] vr, int ldvr, float[] work) {
			int info = 0;
			int len = work.Length;
			SafeNativeMethods.SGGEV(ref jobvl, 1, ref jobvr, 1, ref n, a, ref lda, b, ref ldb, alphar, alphai, beta, vl, ref ldvl, vr, ref ldvr, work, ref len, ref info);
			return info;
		}


		public int Ilaenv(int ispec, string name, string opts, int n1, int n2, int n3, int n4) {
			return SafeNativeMethods.ILAENV(ref ispec, name, name.Length, opts, opts.Length, ref n1, ref n2, ref n3, ref n4);
		}

		#endregion Public Members
	}
}